home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 11 / CU Amiga Magazine's Super CD-ROM 11 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-06].iso / cucd / programming / amoslist / amoslist.mar / 000123_amos-request@svcs1.digex.net_Tue Mar 18 18:50:08 1997.msg < prev    next >
Text File  |  1997-04-01  |  10KB  |  261 lines

  1. Received: from svcs1.digex.net (svcs1.digex.net [204.91.197.224])
  2.     by mail1.access.digex.net (8.8.5/8.8.5) with ESMTP id SAA29014
  3.     for <mcox@access.digex.net>; Tue, 18 Mar 1997 18:50:04 -0500 (EST)
  4. Received: (from daemon@localhost)
  5.     by svcs1.digex.net (8.8.5/8.8.5) id QAA03919
  6.     for amos-out; Tue, 18 Mar 1997 16:42:03 -0500 (EST)
  7. Received: from mail1.access.digex.net (mail1.access.digex.net [205.197.247.2])
  8.     by svcs1.digex.net (8.8.5/8.8.5) with ESMTP id QAA03916
  9.     for <amos-list@svcs1.digex.net>; Tue, 18 Mar 1997 16:42:02 -0500 (EST)
  10. Received: from vifa1.freenet.victoria.bc.ca (uv334@vifa1.freenet.victoria.bc.ca [199.60.222.1])
  11.     by mail1.access.digex.net (8.8.5/8.8.5) with ESMTP id QAA18872
  12.     for <amos-list@access.digex.net>; Tue, 18 Mar 1997 16:41:59 -0500 (EST)
  13. Received: (from uv334@localhost) by vifa1.freenet.victoria.bc.ca (8.7.5/8.7.3) id NAA07908; Tue, 18 Mar 1997 13:42:07 -0800 (PST)
  14. Date: Tue, 18 Mar 1997 13:42:06 -0800 (PST)
  15. From: John Bintz <uv334@freenet.victoria.bc.ca>
  16. Sender: John Bintz <uv334@freenet.victoria.bc.ca>
  17. Reply-To: John Bintz <uv334@freenet.victoria.bc.ca>
  18. Subject: Raycasting for Beginners (was Bending Walls)
  19. To: amos-list@access.digex.net
  20. Message-ID: <Pine.3.89.9703171320.A5765-0100000@vifa1>
  21. MIME-Version: 1.0
  22. Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
  23. Status: RO
  24. X-Status: 
  25.  
  26. Well, Mr. Howarth should be commended for trying a raycaster.  I remember 
  27. when I was tring very desparately to figure out how to make one.  
  28. Fortunately, I found a book that kinda explained it.  After some work, 
  29. though, I finally figured out how to write a fast and accurate ray caster.
  30.  
  31. The way Lee put it, he wrote a very simple, non-trig version of a 
  32. raycaster.  He got the concept of "raycasting" down, its just not useful 
  33. the way he coded it.  To hame a truly 3D game (at least a #D 
  34. representation of a 2D map), he needs Math.  And, as Sinbad says, "Math 
  35. is Power".
  36.  
  37. Here is a copy of my original "I Have A Few Tricks Up My Sleeve..." 
  38. page.  The part about Wolf-3D like raycasters.  If its too big (8k?) then 
  39. feel free to complain.  Here it is...
  40.  
  41. RayCasting and Texture Mapping -- John Bintz, 3D Master  8^)
  42.  
  43. So, you want to write Doom-like games in your spare time? I'm warning you:
  44. once you know how to do this stuff, you'll probably never write another game
  45. with just 2D graphics again...EVER!
  46.  
  47. Here is a very loose algorithm for raycasting and texture mapping:
  48.  
  49. Precompute math tables
  50. Create a map
  51. Create some textures
  52.  
  53. While your game is running
  54. # For each ray in your field of view
  55. ## Cast a ray, detecting horizontal and vertical intersections with blocks
  56. ## Find out the shortest distance to yourself 
  57. ##     from the horizontal & vertical intersections
  58. ## Fix the depth of the ray depending on the view angle
  59. ## Determine the height of the wall
  60. ## Choose a sliver from the texture and zoom it to the appropriate size
  61. # Move the little guy around
  62.  
  63. Now, I'll describe all of these in excruciating detail:
  64.  
  65. Precompute Math Tables
  66.  
  67. For my method of raycasting, you need to know Sines and Cosines of angles.
  68. These are computed by the computer and stored as floating point, which, as all
  69. programmers know, is extremely accurate yet excruciatingly slow. We need to make
  70. them fixed point...not as accurate, but sometimes at least 3 or 4 times
  71. faster.
  72.  
  73. How many degrees will you have to compute? Well, this will
  74. involve that difficult technique known as the ratio. What you need to know is
  75. the screen resolution horizontally, the number of total angles, and the number
  76. of angles in your viewing plane. Your view plane is the number of angles cast
  77. out from your current position to the walls. If you wanted to stick with easy
  78. stuff, have the number of rays cast out equal to the degrees in your view
  79. plane...fast, but blocky. You can use this formula to find out how many angles
  80. to put into the tables:
  81.  
  82. Angles=(360*Rays to cast)/View Angle
  83.  
  84. If you wanted to fill all the lines on the screen, the formula would look
  85. like this:
  86.  
  87. Angles=(360*320)/60
  88.  
  89. Giving the result of 1920 angles. 
  90.  
  91. You could use floating point math to find out how much each angle
  92. will actually measure from 0 to 359, but you can do that on your own.
  93.  
  94. Fixing the angles simply requires you to multiply the floating point number by a
  95. fixed point number, therefore making another fixed point number. I like using
  96. 512, just for the heck of it. Fill your table with fixed trig numbers, and move
  97. on to Step 2...
  98.  
  99. Create A Map
  100.  
  101. This shouldn't be too hard--just an array of elements you can fill with any numbers you want...have
  102. them correspond to the texture to map to the walls, or the light level of each
  103. wall. Just make empty space a value of zero.
  104.  
  105. Cast A Ray
  106.  
  107. This is where you can pretty much think of your own way to do things. Here's an
  108. example from QBasic (ICK! GAG!! RETCH!!!) that is pretty good. It should be
  109. readily convertable to other languages, Amos Basic being the most obvious:
  110.  
  111. FUNCTION newcast (x, y, ang) 
  112.  
  113. angle = (ang + 360) MOD 360 
  114. corner = 0 
  115. 'Some Readily Used Values 
  116.  
  117. IF ang > 90 AND ang
  118.   yadj = halfbsize
  119. ELSE
  120.   yadj = -halfbsize
  121. END IF
  122. IF ang > 0 AND ang 
  123.   xadj = halfbsize
  124. ELSE
  125.   xadj = -halfbsize
  126. END IF
  127. '
  128. 'This is the X Casting.  It looks for intersections on the X (horizontal) axis.
  129. '
  130. IF gcos(angle) = 0 THEN
  131.   xdepth = 1E+10
  132. ELSE
  133.   IF ang > 90 AND ang 
  134.     ybound = INT(y / bsize) * bsize + bsize
  135.     ydelta = bsize
  136.   ELSE
  137.     ybound = INT(y / bsize) * bsize
  138.     ydelta = -bsize
  139.   END IF
  140.   casting = -1
  141.   DO
  142.     ydist = ybound - y
  143.     depth = (ydist * 512) / gcos(angle)
  144.     xdist = (depth * gsin(angle)) / 512
  145.     dx = INT((x - xdist) / bsize)
  146.     IF dx >= 0 AND dx 
  147.       IF map(dx, INT((ybound + yadj) / bsize)) > 0 THEN
  148.         casting = 0
  149.         xdepth = ABS(depth)
  150.         xsliv = ABS(x - xdist) MOD bsize
  151.       ELSE
  152.         ybound = ybound + ydelta
  153.       END IF
  154.     ELSE
  155.       casting = 0
  156.       xdepth = 1E+10
  157.     END IF
  158.   LOOP UNTIL NOT casting
  159. END IF
  160. '
  161. 'The Y Casting Comes Next, looking for Vertical intersections
  162. '
  163. IF gsin(angle) = 0 THEN
  164.   ydepth = 1E+10
  165. ELSE
  166.   IF ang > 0 AND ang 
  167.     xbound = INT(x / bsize) * bsize + bsize
  168.     xdelta = bsize
  169.   ELSE
  170.     xbound = INT(x / bsize) * bsize
  171.     xdelta = -bsize
  172.   END IF
  173.   casting = -1
  174.   DO
  175.     xdist = xbound - x
  176.     depth = (xdist * 512) / gsin(angle)
  177.     ydist = (depth * gcos(angle)) / 512
  178.     dy = INT((y - ydist) / bsize)
  179.     IF dy >= 0 AND dy 
  180.       IF map(INT((xbound + xadj) / bsize), dy) > 0 THEN
  181.         casting = 0
  182.         ydepth = ABS(depth)
  183.         ysliv = ABS(y - ydist) MOD bsize
  184.       ELSE
  185.         xbound = xbound + xdelta
  186.       END IF
  187.     ELSE
  188.       casting = 0
  189.       ydepth = 1E+10
  190.     END IF
  191.   LOOP UNTIL NOT casting
  192. END IF
  193. '
  194. 'This picks which depth to use, depending on which is closest
  195. '
  196. IF xdepth 
  197.   newcast = xdepth
  198.   IF xsliv = 0 THEN corner = -1
  199. ELSE
  200.   newcast = ydepth
  201.   IF ysliv = 0 THEN corner = -1
  202. END IF
  203. END FUNCTION
  204.  
  205. I'm sorry if that wasn't too well explained, but its a very difficult topic
  206. to explain. Just pick up "Tricks of the Game Programming Gurus" by Andrew
  207. LaMothe, and you'll be even more confused!. Try to pick your way through it the
  208. best that you can. If I can hire someone to explain it better, I will;
  209. otherwise, fry some brain cells over my Basic code.
  210.  
  211. Fix the depth
  212.  
  213. Any idiot with a major in Mathematics will know there's a slight problem
  214. with this routine. Think about it...OK, enough thinking. Here's the problem:
  215. When you cast your rays out, you're doing it in a circle. When they hit, they're
  216. working in a rectangular plane. The fix? Make your rectangular world a circular
  217. world, or make your circular world a rectangular one. The first one is easier:
  218. Simply multiply the depth by the cosine of the current view angle. If your view
  219. angle is -10 of your current facing angle, and the depth is 35, then you'd
  220. multiply the cosine of -10 (precomputed, I hope!) by 35, and get 34. Big deal!
  221. Try -30 and 60, at the furthest reaches of your view plane. The result is 51, a
  222. very signifigant fix (with two signifigant digits!). But remember: the angle you
  223. use is RELATIVE to the angle your guy is facing. Not to be sexist, but you can
  224. be a girl, too.
  225.  
  226.  
  227. Draw the Sliver, with or without Textures
  228.  
  229. This part is pretty easy compared to the others: You need the fixed depth
  230. and the size of HALF of your wall. To get the new HALF size of your wall, try
  231. this:
  232.  
  233. New HALF Size=Normal HALF Size/Depth
  234.  
  235. Now, simply subtract from half your display and add to half your display
  236. that value, and your wall can be plotted. A command like:
  237.  
  238. Cls 15,X,100-NHS to X+1,100+NHS
  239.  
  240. will do the trick nicely.
  241.  
  242. For those who want texture mapping, you should save that XSLIV or YSLIV
  243. value in the code above, as this tells you what sliver on the texture to use. If
  244. your blocks are 64 pixels large, then the sliver value will be from 0 to 63.
  245. Then, simply use a Zoom-like command to put it at its appropriate size:
  246.  
  247. Zoom 1,SLIV,0,SLIV+1,63 to 0,X,100-NHS,X+1,100+NHS
  248.  
  249. Hope this helps!
  250.  
  251. #@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@
  252.         John C. Bintz - * uv334@freenet.victoria.bc.ca *
  253. @#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#*@#
  254. Come Visit Internext Software - the home of great Amiga software!
  255.     http://www.dragonfire.net/~JohnBintz/inext/inextsoft.html
  256. *#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#@*#
  257.  
  258.  
  259.